package com.corpgovernment.common.supplier;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.corpgovernment.common.base.BaseUserInfo;
import com.corpgovernment.common.bo.ReplaceOrderInfo;
import com.corpgovernment.common.bo.ReplaceSupplierUidBo;
import com.corpgovernment.common.config.CommonApplicationContext;
import com.corpgovernment.common.config.Config;
import com.corpgovernment.common.dataloader.CommonOrderCenterDataloader;
import com.corpgovernment.common.dataloader.CommonOrganizationDataloader;
import com.corpgovernment.common.dataloader.ReplaceOrderDataloader;
import com.corpgovernment.common.dto.GetEmployeeOpenCardReq;
import com.corpgovernment.common.dto.GetEmployeeOpenCardRsp;
import com.corpgovernment.common.dto.GetOrderInfoDtoRsp;
import com.corpgovernment.common.dto.OrderUserInfoRsp;
import com.corpgovernment.common.dto.SupplierCompanyDto;
import com.corpgovernment.common.utils.LogSplicingUtils;
import com.ctrip.corp.obt.generic.core.context.UserInfoContext;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Lists;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ReplaceSupplierUidUtil {

    /**
     * 携程编码
     */
    private static final String SUPPLIER_CODE_CTRIP = "ctrip";

    /**
     * 替换用户卡号-缓存前缀
     */
    private static final String CACHE_PREFIX = "ReplaceOrderInfo";

    /**
     * 系统中corpId(供应商公司编码)会使用的名称
     */
    private static final List<String> CorpColumnName =
            Collections.unmodifiableList(Lists.newArrayList("corpId", "CorpId", "corpID"));
    /**
     * 系统中uid(供应商用户编码)会使用的名称
     */
    private static final List<String> uidColumnName =
            Collections.unmodifiableList(Lists.newArrayList("uid", "uId", "Uid", "uID"));
    /**
     * 系统中orderId(订单号)会使用的名称
     */
    private static final List<String> orderIdColumnName =
            Collections
                    .unmodifiableList(Lists.newArrayList("orderId", "orderID", "platformOrderId", "platformOrderID"));

    /**
     * 替换调用供应商接口中的UID
     * 命中条件：1:在商旅卡开成功 2:命中企业订购中的公司卡号
     * @return
     */
    public static String replaceEmployeeId(String supplierCode, String requestBody) {
        if (!SUPPLIER_CODE_CTRIP.equals(supplierCode)) {
            return requestBody;
        }
        StringBuilder logContext = new StringBuilder();
        LogSplicingUtils.addLogContext(logContext, "开始处理UID替换操作");
        LogSplicingUtils.addLogContext(logContext, "requestBody：%s", requestBody);
        try {
            // 获取需要替换UID的数据
            Map<String, ReplaceSupplierUidBo.Supplier> corpMap = getSupplierConfigMap(logContext);
            // 获取树形结构
            JsonNode tree = JsonUtils.getJsonNode(requestBody);
            // 处理替换操作
            return filterCorpNode(tree, corpMap, ReplaceSupplierUidBo.getHistoryOrderMap(), logContext);
        } catch (Exception ex) {
            log.error("替换供应商UID异常", ex);
            LogSplicingUtils.addLogContext(logContext, "发生异常：%s", ex);
            return requestBody;
        } finally {
            log.info("{}", logContext);
        }
    }

    /**
     * 过滤公司节点
     */
    private static String filterCorpNode(JsonNode tree, Map<String, ReplaceSupplierUidBo.Supplier> corpMap,
            Map<String, String> historyOrderMap, StringBuilder logContext) throws Exception {
        for (String corpName : CorpColumnName) {
            // 获取json字符串中所有的corpId
            List<JsonNode> corpJsonNode = tree.findParents(corpName);
            // json中未命中corpId
            if (CollectionUtils.isEmpty(corpJsonNode)) {
                continue;
            }
            for (JsonNode corpNode : corpJsonNode) {
                String corpId = corpNode.get(corpName).asText();
                ReplaceSupplierUidBo.Supplier supplier = corpMap.get(corpId);
                // 是否命中配置的公司ID，命中则进行替换uid操作
                if (Objects.isNull(supplier)) {
                    LogSplicingUtils.addLogContext(logContext, "未命中Apollo中配置的corpId：%s", corpId);
                    continue;
                }
                String result = filterUidNode(tree, corpNode, supplier, historyOrderMap, logContext);
                if (StringUtils.isNotBlank(result)) {
                    return result;
                }
            }
        }
        return tree.toString();
    }

    /**
     * 过滤UID节点
     */
    private static String filterUidNode(JsonNode tree, JsonNode corpNode, ReplaceSupplierUidBo.Supplier supplier,
            Map<String, String> historyOrderMap, StringBuilder logContext) throws Exception {
        for (String uidName : uidColumnName) {
            JsonNode uidJsonNode = corpNode.get(uidName);
            if (Objects.nonNull(uidJsonNode) && supplier.getSupplierUid().contains(uidJsonNode.asText())) {
                // 使用下单的时候用户uid进行操作
                String uid = findUidByOrderUser(tree, logContext);
                if (StringUtils.isNotBlank(uid)) {
                    ((ObjectNode)corpNode).put(uidName, uid);
                    LogSplicingUtils.addLogContext(logContext, "uidName：%s;tree:%s", uidName, tree.toString());
                    return tree.toString();
                }

                uid = filterOrderNode(tree, historyOrderMap, logContext);
                LogSplicingUtils.addLogContext(logContext, "根据订单号获取预定人：%s", uid);
                if (StringUtils.isBlank(uid)) {
                    BaseUserInfo baseUserInfo = UserInfoContext.getContextParams(BaseUserInfo.class);
                    LogSplicingUtils.addLogContext(logContext, "baseUserInfo：%s", JsonUtils.toJsonString(baseUserInfo));
                    if (null == baseUserInfo || StringUtils.isBlank(baseUserInfo.getUid())) {
                        continue;
                    }
                    uid = baseUserInfo.getUid();
                }

                GetEmployeeOpenCardRsp employeeOpenCardInfo = getEmployeeOpenCard(uid);
                LogSplicingUtils.addLogContext(logContext, "开卡信息：%s", JsonUtils.toJsonString(employeeOpenCardInfo));
                if (Objects.isNull(employeeOpenCardInfo)
                        || StringUtils.isBlank(employeeOpenCardInfo.getSupplierUid())) {
                    continue;
                }
                ((ObjectNode)corpNode).put(uidName, employeeOpenCardInfo.getSupplierUid());
                return tree.toString();
            }
        }
        return null;
    }

    /**
     * 根据订单号获取订单用户关联表的数据
     * @param tree
     * @param logContext
     * @return
     */
    private static String findUidByOrderUser(JsonNode tree, StringBuilder logContext) {
        try {
            for (String orderIdName : orderIdColumnName) {
                JsonNode orderIdJsonNode = tree.findValue(orderIdName);
                if (Objects.nonNull(orderIdJsonNode) && StringUtils.isNotBlank(orderIdJsonNode.asText())) {
                    String orderId = Optional.ofNullable(orderIdJsonNode.asText()).orElse("");
                    OrderUserInfoRsp orderUser = getCommonOrderCenterDataloader().getOrderUser(orderId);
                    LogSplicingUtils.addLogContext(logContext, "orderUser：%s", JsonUtils.toJsonString(orderUser));
                    if (!Optional.ofNullable(orderUser).map(v -> StringUtils.isNotBlank(v.getSupplierUid()))
                            .orElse(false)) {
                        continue;
                    }
                    return orderUser.getSupplierUid();
                }
            }
        } catch (Exception e) {
            log.error("findUidByOrderUser", e);
        }

        return null;
    }

    /**
     * 过滤公司节点
     */
    private static String filterOrderNode(JsonNode tree, Map<String, String> historyOrderMap, StringBuilder logContext)
            throws Exception {
        for (String orderIdName : orderIdColumnName) {
//            JsonNode orderIdJsonNode = tree.get(orderIdName);
            JsonNode orderIdJsonNode = tree.findValue(orderIdName);
            if (Objects.nonNull(orderIdJsonNode) && StringUtils.isNotBlank(orderIdJsonNode.asText())) {
                String orderId = Optional.ofNullable(orderIdJsonNode.asText()).orElse("");
                LogSplicingUtils.addLogContext(logContext, "filterOrderNode->orderId: %s", orderId);
                // 校验是否历史订单
                if (checkHistoryOrder(orderId, historyOrderMap)) {
                    LogSplicingUtils.addLogContext(logContext, "命中历史订单: %s", orderId);
                    throw new Exception("命中历史订单");
                }
                // 获取缓存中的订单信息
                ReplaceOrderInfo replaceOrderInfo = getReplaceOrderInfo(orderId);
                LogSplicingUtils.addLogContext(logContext, "replaceOrderInfo: %s",
                        JsonUtils.toJsonString(replaceOrderInfo));
                if (Objects.nonNull(replaceOrderInfo) && StringUtils.isNotBlank(replaceOrderInfo.getBookUid())) {
                    LogSplicingUtils.addLogContext(logContext, "命中缓存订单: %s", JsonUtils.toJsonString(replaceOrderInfo));
                    return replaceOrderInfo.getBookUid();
                }

                GetOrderInfoDtoRsp getOrderInfoDtoRsp =
                        getCommonOrderCenterDataloader().getOrderInfoBySupplierOrderId(orderId);
                if (Objects.nonNull(getOrderInfoDtoRsp)) {
                    LogSplicingUtils.addLogContext(logContext, "数据库中订单信息：%s",
                            JsonUtils.toJsonString(getOrderInfoDtoRsp));
                    return getOrderInfoDtoRsp.getUid();
                }
            }
        }
        return null;
    }

    /**
     * 查询开卡信息
     */
    private static GetEmployeeOpenCardRsp getEmployeeOpenCard(String uid) {
        if (StringUtils.isBlank(uid)) {
            return null;
        }
        GetEmployeeOpenCardReq getEmployeeOpenCardReq = new GetEmployeeOpenCardReq();
        getEmployeeOpenCardReq.setUid(uid);
        String switchInfo = Config.defaultConfig().get("switch");
        GetEmployeeOpenCardRsp getEmployeeOpenCardRsp;
        if("T".equals(switchInfo)){
            getEmployeeOpenCardRsp = getCommonOrganizationDataloader().getEmployeeOpenCardRsp(getEmployeeOpenCardReq);
        }else {
            getEmployeeOpenCardRsp = getCommonOrganizationDataloader().getEmployeeOpenCardInfo(getEmployeeOpenCardReq);
        }
        return getEmployeeOpenCardRsp;
    }

    /**
     * 获取需要替换的公司
     */
    private static Map<String, ReplaceSupplierUidBo.Supplier> getSupplierConfigMap(StringBuilder logContext) {
        // 查询需要替换员工Id的公司
        List<ReplaceSupplierUidBo.Supplier> suppliers = ReplaceSupplierUidBo.getReplaceSupplierUidBo();
        // 转换Map 简化时间复杂度
        Map<String, ReplaceSupplierUidBo.Supplier> corpMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(suppliers)) {
            corpMap = suppliers.stream().collect(Collectors.toMap(ReplaceSupplierUidBo.Supplier::getSupplierCorp,
                    Function.identity(), (k1, k2) -> k1));
        }
        LogSplicingUtils.addLogContext(logContext, "Apollo配置: %s", JsonUtils.toJsonString(corpMap));
        String switchInfo = Config.defaultConfig().get("switch");
        List<SupplierCompanyDto> supplierCompanyList;
        if("T".equals(switchInfo)){
             supplierCompanyList = getCommonOrganizationDataloader().getSupplierCompanySDK();
        }else {
            supplierCompanyList = getCommonOrganizationDataloader().getSupplierCompanySoa();
        }

        // 查询数据库命中则替换
        LogSplicingUtils.addLogContext(logContext, "supplierCompanyList: %s",
                JsonUtils.toJsonString(supplierCompanyList));

        if (CollectionUtils.isNotEmpty(supplierCompanyList)) {
            for (SupplierCompanyDto supplierCompany : supplierCompanyList) {
                if (!SUPPLIER_CODE_CTRIP.equals(supplierCompany.getSupplierCode())) {
                    continue;
                }
                ReplaceSupplierUidBo.Supplier supplier = corpMap.get(supplierCompany.getSupplierCorpId());
                if (Objects.isNull(supplier)) {
                    supplier = new ReplaceSupplierUidBo.Supplier();
                    supplier.setSupplierCorp(supplierCompany.getSupplierCorpId());
                    supplier.setSupplierUid(supplierCompany.getSupplierUid());
                    corpMap.put(supplierCompany.getSupplierCorpId(), supplier);
                } else {
                    if (supplier.getSupplierUid().contains(supplierCompany.getSupplierUid())) {
                        continue;
                    }
                    supplier.setSupplierUid(supplier.getSupplierUid() + "," + supplierCompany.getSupplierUid());
                    corpMap.put(supplierCompany.getSupplierCorpId(), supplier);
                }
            }
        }
        return corpMap;
    }

    /**
     * 校验是否历史数据
     * @return
     */
    private static boolean checkHistoryOrder(String orderId, Map<String, String> historyOrderMap) {
        if (orderId.length() >= 13 && orderId.contains("0000")) {
            return false;
        }
        String historyOrderId = historyOrderMap.get(orderId);
        if (StringUtils.isNotBlank(historyOrderId)) {
            return true;
        }
        return false;
    }

    private static CommonOrganizationDataloader getCommonOrganizationDataloader() {
        return CommonApplicationContext.getApplicationContext()
                .getBean("commonOrganizationDataloader", CommonOrganizationDataloader.class);
    }

    private static CommonOrderCenterDataloader getCommonOrderCenterDataloader() {
        return CommonApplicationContext.getApplicationContext()
                .getBean("commonOrderCenterDataloader", CommonOrderCenterDataloader.class);
    }

    private static ReplaceOrderDataloader getReplaceOrderDataloader() {
        return CommonApplicationContext.getApplicationContext()
                .getBean("replaceOrderDataloader", ReplaceOrderDataloader.class);
    }

    /**
     * 替换用户卡号-存入缓存
     */
    public static void saveReplaceOrderInfo(ReplaceOrderInfo replaceOrderInfo) {
        try {
            if (StringUtils.isNotBlank(replaceOrderInfo.getOrderId())) {
                getReplaceOrderDataloader().saveReplaceOrderInfo(
                        String.format("%s_%s", CACHE_PREFIX, replaceOrderInfo.getOrderId()), replaceOrderInfo,
                        60 * 60 * 24 * 15);
            }
            if (StringUtils.isNotBlank(replaceOrderInfo.getSupplierOrderId())) {
                getReplaceOrderDataloader().saveReplaceOrderInfo(
                        String.format("%s_%s", CACHE_PREFIX, replaceOrderInfo.getSupplierOrderId()), replaceOrderInfo,
                        60 * 60 * 24 * 15);
            }
        } catch (Exception e) {
            log.error("替换用户卡号存入缓存异常：{}", e);
        }
    }

    /**
     * 替换用户卡号-获取缓存
     */
    public static ReplaceOrderInfo getReplaceOrderInfo(String orderId) {
        return getReplaceOrderDataloader().getReplaceOrderInfo(String.format("%s_%s", CACHE_PREFIX, orderId));
    }

}
